package com.minimalist.common.feign.config;

import com.minimalist.common.feign.monitor.FeignDegradeMonitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Feign 降级事件监听器
 *
 * @author 11987
 */
@Component
public class FeignDegradeEventListener{
    private static final Logger log = LoggerFactory.getLogger(FeignDegradeEventListener.class);

    @Autowired
    private FeignDegradeMonitor degradeMonitor;

    // 用于统计各服务降级次数
    private final Map<String, AtomicInteger> degradeCountMap = new ConcurrentHashMap<>();

    // 最近一次统计时间
    private long lastReportTime = System.currentTimeMillis();

    // 统计报告间隔（毫秒）
    private static final long REPORT_INTERVAL = 60000; // 1分钟

    @Async
    @EventListener
    public void handleFeignDegradeEvent(FeignDegradeEvent event){
        // 增加服务降级计数
        degradeCountMap.computeIfAbsent(event.getServiceName(), k -> new AtomicInteger(0))
                .incrementAndGet();

        // 记录详细日志，包含异常信息和格式化后的时间戳
        if (event.getCause() != null){
            StringWriter sw = new StringWriter();
            event.getCause().printStackTrace(new PrintWriter(sw));

            log.warn("Feign降级详情 - 服务: {}, 降级ID: {}, 时间: {}, 异常: {}\n异常堆栈: {}",
                    event.getServiceName(),
                    event.getDegradeId(),
                    event.getFormattedTimestamp(), // 使用格式化后的时间戳
                    event.getCauseMessage(),
                    sw.toString());
        } else{
            log.warn("Feign降级详情 - 服务: {}, 降级ID: {}, 时间: {}, 异常: 未知原因",
                    event.getServiceName(),
                    event.getDegradeId(),
                    event.getFormattedTimestamp()); // 使用格式化后的时间戳
        }

        // 更新监控统计
        degradeMonitor.recordDegrade(event.getServiceName(), event.getCauseMessage());

        // 定期输出统计报告
        long now = System.currentTimeMillis();
        if (now - lastReportTime > REPORT_INTERVAL){
            reportDegradeStatistics();
            lastReportTime = now;
        }
    }

    /**
     * 输出降级统计报告
     */
    private synchronized void reportDegradeStatistics(){
        if (degradeCountMap.isEmpty()){
            return;
        }

        StringBuilder report = new StringBuilder("Feign降级统计报告:\n");
        degradeCountMap.forEach((service, count) -> report.append("- 服务: ").append(service)
                .append(", 降级次数: ").append(count.get())
                .append("\n"));

        log.warn(report.toString());

        // 重置计数器
        degradeCountMap.forEach((service, count) -> count.set(0));
    }
}